package com.bj.util;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import javax.persistence.Column;
import javax.persistence.Transient;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 12-2-7
 * Time: 上午12:28
 * To change this template use File | Settings | File Templates.
 */
public class CodeTools {

    private static Map <Class,Map> ClassMap= new HashMap<Class, Map>();

    public static String ENCODING = "UTF-8";

    public static List split(String value,String key){
        List list = new ArrayList();
        if (org.apache.commons.lang.StringUtils.isNotEmpty(value)) {
            String[] ageArray = org.apache.commons.lang.StringUtils.split(value, key);
            if (ArrayUtils.isNotEmpty(ageArray)) {
                list.addAll(Arrays.asList(ageArray));
            }
        }
        return list;
    }

    public static boolean isExistsProperty(Object bean,String name){
        Field [] fields = bean.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            if(name.equals(field.getName())){
                return true;
            }
        }
        return false;
    }

    public static String getName(String inName){
        int i = 0 ;
        StringBuffer outString =new StringBuffer();
        for (StringTokenizer stringTokenizer = new StringTokenizer(inName,"_"); stringTokenizer.hasMoreTokens(); i ++ ) {
            String s = stringTokenizer.nextToken();
            if(i != 0){
                s = s.substring(0,1).toUpperCase() + s.substring(1,s.length());
            }
            outString.append(s);
        }
        return outString.toString();
    }

    public static void main(String [] arge) throws IOException {

        //System.out.println(" = " + isExistsProperty(new Subject(),"userid") );

    }

    public static void main1(String [] arge) throws IOException {
        //

       List list = org.apache.commons.io.FileUtils.readLines(new File("D:/abcd.txt"));
        for (int i = 0; i < list.size(); i++) {
            String s = (String) list.get(i);
            String name = org.apache.commons.lang.StringUtils.substringBetween(s, "`", "`");
            String column = "@Column(name = \""+ name +"\")";
            int type = 0;
            String pro = null;
            String lower = s.toLowerCase();
            if( lower.indexOf("varchar") > -1 ){
                type = 1;
                pro = "public String";
            } else if (lower.indexOf("datetime") > -1){
                type = 2;
                pro = "public Date";
            } else if (lower.indexOf("tinyint") > -1){
                type = 3;
                pro = "public Integer";
            } else if (lower.indexOf("text") > -1){
                type = 1;
                pro = "public String";
            } else if (lower.indexOf("int") > -1){
                type = 4;
                pro = "public Long";
            } else if (lower.indexOf("float") > -1){
                type = 4;
                pro = "public Float";
            }
//            System.out.println(column);
//            System.out.println(pro + " " + getName(name) + ";" );
//            System.out.println();
        }
    }

    public static Map getURLParameters(String parameters){
        Map <Integer,String> paramMap = new HashMap<Integer, String>();
        if( org.apache.commons.lang.StringUtils.isNotEmpty(parameters) ){
            parameters = parameters.trim();
            if( parameters.subSequence(0,1).equals("_") && parameters.length() > 1 ){
                String [] s = parameters.split("_");
                for (int i = 1; i < s.length; i++) {
                    String s1 = s[i];
                    paramMap.put(i-1,s1);
                }
            }
        }
        return paramMap;
    }

    public static List getIdByList(List list){
        List valueList = new ArrayList();
        if (CollectionUtils.isNotEmpty(list)) {
            for (int i = 0; i < list.size(); i++) {
                Object bean = list.get(i);
                if (bean == null) {
                    continue;
                }
                String methodName = "getId";
                try {
                    Method method = bean.getClass().getMethod(methodName, null);
                    Object value = method.invoke(bean, null);
                    valueList.add(value);
                } catch (Exception e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }
        }
        return valueList;
    }

    public static Map getMapByListId(List list){
        Map valueMap = new HashMap();
        if( CollectionUtils.isNotEmpty(list) ){
            for (int i = 0; i < list.size(); i++) {
                Object bean =  list.get(i);
                if( bean == null ){
                    continue;
                }
                String methodName = "getId";
                try {
                    Method method = bean.getClass().getMethod(methodName, null);
                    Object value = method.invoke(bean, null);
                    valueMap.put(value,bean);
                } catch (Exception e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }
        }
        return valueMap;
    }

    public static Map getFieldsMap(Class clazz){
        Map fieldMap = ClassMap.get(clazz);
        if (fieldMap == null) {
            fieldMap = new HashMap();
            Field[] Fields = clazz.getFields();
            for (int i = 0; i < Fields.length; i++) {
                Field field = Fields[i];
                if (field.getAnnotation(Transient.class) == null  && !field.getName().equals("willBeSaved") ) {
                    Column column = field.getAnnotation(Column.class);
                    String name = column != null && org.apache.commons.lang.StringUtils.isNotEmpty(column.name()) ? column.name() : field.getName();
                    fieldMap.put( name , field );
                }
            }
            ClassMap.put(clazz, fieldMap);
        }
        return fieldMap;
    }


    public static void toEntity( Map <String,Object> data , Object entity ,String prefix ){

        if (entity == null || data == null || data.size() == 0) {
            return;
        }
        Map fieldMap = getFieldsMap(entity.getClass());
        for (String s : data.keySet()) {
            String name = s;
            if (prefix != null) {
                if (s.indexOf(prefix) != 0) {
                    continue;
                }
                name = s.replaceFirst(prefix + "_", "");
            }
            Field field = (Field) fieldMap.get(name);
            if (field == null) {
                continue;
            }
            Object value = data.get(s);
            String methodName = "set" + getFiledMethod(field.getName());
            try {
                Method method = entity.getClass().getMethod(methodName, new Class[]{field.getType()});
                if ( value == null ) {
                    method.invoke(entity, new Object[]{null});
                    continue;
                }
                if (field.getType() == Date.class) {
                    if (value instanceof Date) {
                        value = new Date(((Date) value).getTime());
                    }
                } else if (field.getType() == Integer.class || field.getType() == Long.class || field.getType() == Double.class || field.getType() == Byte.class || field.getType() == Float.class || field.getType() == Short.class) {
                    if (value instanceof Number) {
                        Number number = (Number) value;
                        if (field.getType() == Integer.class) {
                            value = new Integer(number.intValue());
                        } else if (field.getType() == Double.class) {
                            value = new Double(number.doubleValue());
                        } else if (field.getType() == Byte.class) {
                            value = new Byte(number.byteValue());
                        } else if (field.getType() == Float.class) {
                            value = new Float(number.floatValue());
                        } else if (field.getType() == Short.class) {
                            value = new Short(number.shortValue());
                        } else if (field.getType() == Long.class) {
                            value = new Long(number.longValue());
                        }
                    }
                }
                method.invoke(entity, new Object[]{value});
            } catch (Exception e) {
                System.out.println(field.getName());
                System.out.println(field.getType());
                System.out.println(value.getClass());
//                System.out.println("CodeTools.toEntity");
                e.printStackTrace();
            }

        }
    }



    public static String getSqlByEntity(Class clazz,String prefix){
        StringBuffer sql = new StringBuffer();
        Map <String,String> fieldsMap = getFieldsMap(clazz);
        for (String name : fieldsMap.keySet()) {
            if( prefix != null){
                name = prefix + "." + name + " as " + prefix + "_" + name ;
            }
            sql.append( sql.length() == 0 ?  name : "," + name );
        }
        return sql.toString();
    }


    public static boolean isBig0(Number number) {
        if (number == null) {
            return false;
        }

        if (number instanceof Long) {
            if ((Long) number > 0) {
                return true;
            }
        }
        return false;
    }

    public static boolean isNotBig0(Number number) {
        return !isBig0(number);
    }


    public static String encodeURIComponent(String s) {
        return encodeURIComponent(s, ENCODING);
    }

    public static String encodeURIComponent(String s, String encoding) {
        // Encode URL
        if (s == null) {
            s = "";
        }
        try {
            s = URLEncoder.encode(s, encoding);
        } catch (Exception e) {
        }
        s = s.replaceAll("\\+", "%20");
        s = s.replaceAll("%2B", "+");
        return s;
    }

    public static String decodeURIComponent(String s) {
        return decodeURIComponent(s, ENCODING);
    }

    public static String decodeURIComponent(String s, String encoding) {
        s = s.replaceAll("%u[0-9a-fA-F]{4}", "");
        s = s.replaceAll("\\+", "%2B");
        s = s.replaceAll("%20", "+");
        try {
            s = URLDecoder.decode(s, encoding);
        } catch (Exception e) {
        }
        return s;
    }


    /**
     * 将指定对象属性名称和属性值转化为Map键值对
     *
     * @param bean
     * @return
     */
    public static Map toMap(Object bean) {
        return toMapByAnnotation(bean, null);
    }

    public static Map toMapByAnnotation(Object bean, Class cls) {
        Map value = new HashMap();
        if (bean == null) {
            return value;
        }
        Field fields[] = bean.getClass().getFields();
        Field DeclaredFields[] = bean.getClass().getDeclaredFields();
        List<Field>list = new ArrayList();

        CollectionUtils.addAll(list,fields);
        CollectionUtils.addAll(list,DeclaredFields);

        boolean isNull = cls == null;

        for (int i = 0; i < list.size(); i++) {
            Field field = list.get(i);
            Class clazz = field.getType();
            if (isBaseType(clazz)) {
                boolean isEx = isNull ? true : field.getAnnotation(cls) != null;
                if (isEx) {
                    setProperty(bean, value, field);
                }
            }
        }
        return value;
    }


    public static Map toMapByExpose(Object bean) {
        return toMapByAnnotation(bean, Expose.class);
    }

    public static Set getKeyByValue(Map data,Object value){

        if( value == null ){
            return null;
        }

        Set set = new HashSet();

        if( MapUtils.isNotEmpty(data) ){
            for (Object o : data.keySet()) {
                if( value.equals(data.get(o)) ){
                    set.add(o);
                }
            }
        }

        return set;
    }

    public static void setProperty(Object bean, Map value, Field field) {

        String filedName = field.getName();
        String methodName = "get" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1, filedName.length());
        try {
            Method method = bean.getClass().getMethod(methodName, null);
            Class clazz = method.getReturnType();
            if (isBaseType(clazz)) {
                Object object = method.invoke(bean, null);
                if (object != null) {
                    value.put(field.getName(), object);
                }
            }
        } catch (Exception ex) {
            //ex.printStackTrace();
        }
    }

    /**
     * @param clazz
     * @return
     */
    private static boolean isBaseType(Class clazz) {
        if( clazz.isPrimitive() ){
            return true;
        }
        if (clazz == String.class) {
            return true;
        }
        if (clazz == Date.class) {
            return true;
        }
        if (clazz == Integer.class) {
            return true;
        }
        if (clazz == Long.class) {
            return true;
        }
        if (clazz == Double.class) {
            return true;
        }
        if (clazz == Byte.class) {
            return true;
        }
        if (clazz == Float.class) {
            return true;
        }
        if (clazz == Short.class) {
            return true;
        }
        if (clazz == Boolean.class) {
            return true;
        }
        return false;
    }

    public static String getFiledMethod(String filedName) {
        return filedName.substring(0, 1).toUpperCase() + filedName.substring(1, filedName.length());
    }

    /**
     * 允许存在null值
     * @param list
     * @param filedName
     * @return
     */
    public static List getPropertyListAllowNull(List list, String filedName) {
        return getPropertyList(list , filedName ,true);
    }

    /**
     * 不允许存在null值
     * @param list
     * @param filedName
     * @return
     */
    public static List getPropertyList(List list, String filedName) {
        return getPropertyList(list , filedName ,false);
    }


    public static <T> List<T> getNumberByString(String numbers,Class<T> clazz){
        List list = new ArrayList();
        if (StringUtils.isEmpty(numbers))
            return null;
        String REGEX = "[\\d.]+";
        Matcher m = Pattern.compile(REGEX, Pattern.CASE_INSENSITIVE).matcher(numbers);
        while (m.find()) {
            try {
                String value = m.group(0);
                Double d = Double.valueOf(value);
                if( clazz == Integer.class ){
                    list.add(d.intValue());
                } else if(clazz == Float.class){
                    list.add(d.floatValue());
                } else if(clazz == Long.class){
                    list.add(d.longValue());
                } else if(clazz == Double.class){
                    list.add(d);
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return list;
    }

    public static List getPropertyList(List list, String filedName,boolean allowNull) {
        List returnValue = new ArrayList();
        if (CollectionUtils.isNotEmpty(list)) {
            for (int i = 0; i < list.size(); i++) {
                Object bean = list.get(i);
                Object value = null;
                try {
                    if (bean != null) {
                        value = PropertyUtils.getProperty(bean, filedName);
                    }
                    if (value != null || (allowNull && value == null)) {
                        returnValue.add(value);
                    }
                } catch (Exception e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }
        }
        return returnValue;
    }

}
